﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Dominio;
using System.Data.Objects;

namespace Persistencia
{
    public class UsuarioPersistencia
    {

        #region Mapping Entities

        public USUARIO GetUsuarioEntity(Usuario usuario)
        {
            USUARIO usuarioEntity = new USUARIO();
            usuarioEntity.NOMBRE = usuario.Nombre;
            usuarioEntity.APELLIDO = usuario.Apellido;
            usuarioEntity.USERNAME = usuario.NombreUsuario;
            usuarioEntity.PASSWORD = usuario.Password;
            usuarioEntity.EMAIL = usuario.Email;
            return usuarioEntity;
        }

        #endregion


        #region Mapping Domain

        public Permiso GetPermisoDomain(PERMISO permisoEntity)
        {
            Permiso permiso = new Permiso();

            permiso.Id = permisoEntity.ID;
            permiso.Nombre = permisoEntity.NOMBRE;

            return permiso;
        }

        public Usuario GetUsuarioDomain(USUARIO usuarioEntity)
        {
            Usuario usuario = new Usuario();
            usuario.Id = usuarioEntity.ID;
            usuario.Nombre = usuarioEntity.NOMBRE;
            usuario.Apellido = usuarioEntity.APELLIDO;
            usuario.NombreUsuario = usuarioEntity.USERNAME;
            usuario.Password = usuarioEntity.PASSWORD;
            usuario.Email = usuarioEntity.EMAIL;
            List<Rol> roles = GetRolesByUserID(usuario.Id);
            if (roles != null)
            {
                usuario.Roles = roles;
            }
            //if (usuarioEntity.USUARIO_ROL != null)
            //{
            //    usuario.Roles = new List<Rol>();
            //    foreach (Rol r in GetRolesByUserID(usuarioEntity.ID))
            //    {
            //        usuario.Roles.Add(r);
            //    }
            //}
            return usuario;
        }

        public Rol GetRolDomain(ROL rolEntity)
        {
            Rol rol = new Rol();
            rol.Id = rolEntity.ID;
            rol.Tipo = rolEntity.NOMBRE;


            if (rolEntity.ROL_PERMISO != null)
            {
                rol.Permisos = new List<Permiso>();

                foreach (PERMISO p in GetPermisosByRolID(rol.Id))
                {
                    rol.Permisos.Add(GetPermisoDomain(p));
                }
            }
            return rol;
        }

        #endregion


        #region Usuario

        public void InsertarUsuario(Usuario usuario)
        {
            USUARIO u = GetUsuarioEntity(usuario);
            using (OlimpycsLondonEntities entities = new OlimpycsLondonEntities())
            {
                entities.USUARIO.AddObject(u);
                entities.SaveChanges();
            }

            //inserto roles de usuario

            foreach (Rol r in usuario.Roles)
            {
                InsertUsuarioRol(u.ID, r.Id);
            }
        }

        private void InsertUsuarioRol(int userID, int rolId)
        {
            using (OlimpycsLondonEntities context = new OlimpycsLondonEntities())
            {
                USUARIO_ROL ur = new USUARIO_ROL();
                ur.USUARIO1Reference.Value = context.USUARIO.FirstOrDefault(u => u.ID == userID);
                ur.ROL1Reference.Value = context.ROL.FirstOrDefault(r => r.ID == rolId);
                context.AddToUSUARIO_ROL(ur);
                context.SaveChanges();
            }
        }

        public void EliminarUsuario(Usuario usuario)
        {

            using (OlimpycsLondonEntities context = new OlimpycsLondonEntities())
            {
                try
                {
                    USUARIO usu = context.USUARIO.Include("USUARIO_ROL").FirstOrDefault(U => U.ID == usuario.Id);
                    //Elimino todas las relaciones usuario_rol
                    List<USUARIO_ROL> listAux = new List<USUARIO_ROL>();
                    listAux.InsertRange(0, usu.USUARIO_ROL);
                    foreach (USUARIO_ROL usu_rol in listAux)
                    {
                        context.DeleteObject(usu_rol);
                    }
                    context.DeleteObject(usu);
                    context.SaveChanges();
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }
        }


        public List<Usuario> UsuariosSiguenParticipante(int idParticipante)
        {

            List<Usuario> usuarios = new List<Usuario>();

            using (OlimpycsLondonEntities entities = new OlimpycsLondonEntities())
            {
                List<USUARIO> usuariosBD = ((from u in entities.USUARIO
                                             join ups in entities.USUARIO_PARTICIPANTE_SEGUIDO on u.ID equals ups.USUARIO
                                             join p in entities.PARTICIPANTE on ups.PARTICIPANTE equals p.ID
                                             where p.ID == idParticipante
                                             select u) as ObjectQuery<USUARIO>).ToList();

                Usuario usuario = null;
                foreach (USUARIO usuarioBd in usuariosBD)
                {
                    usuario = GetUsuarioDomain(usuarioBd);
                    usuarios.Add(usuario);
                }
            }

            return usuarios;


        }


        public void ModificarUsuario(Usuario usuario)
        {
            using (OlimpycsLondonEntities context = new OlimpycsLondonEntities())
            {
                var usuarioEntity = context.USUARIO.Include("USUARIO_ROL").FirstOrDefault(u => u.ID == usuario.Id);
                usuarioEntity.NOMBRE = usuario.Nombre;
                usuarioEntity.APELLIDO = usuario.Apellido;
                usuarioEntity.USERNAME = usuario.NombreUsuario;
                usuarioEntity.PASSWORD = usuario.Password;
                usuarioEntity.EMAIL = usuario.Email;

                //Elimino todas las relaciones usuario_rol
                List<USUARIO_ROL> listUsuRol = context.USUARIO_ROL.Where(ur => ur.USUARIO1.ID == usuario.Id).ToList();
                foreach (USUARIO_ROL usu_rol in listUsuRol)
                {
                    context.DeleteObject(usu_rol);
                }

                // inserto nuevamente todos las relaciones usuario_rol en funcion de los nuevos roles del usuario
                if (usuario.Roles != null)
                {
                    foreach (Rol rol in usuario.Roles)
                    {
                        InsertUsuarioRol(usuarioEntity.ID, rol.Id);

                    }
                }
                context.SaveChanges();

            }
        }



        public Usuario GetUsuario(string usrName)
        {
            Usuario usuario = null;

            using (OlimpycsLondonEntities entities = new OlimpycsLondonEntities())
            {
                USUARIO usuarioDB = entities.USUARIO.FirstOrDefault((u => u.USERNAME == usrName));

                if (usuarioDB != null)
                    usuario = GetUsuarioDomain(usuarioDB);
            }

            return usuario;

        }

        public List<Usuario> GetAllUsers()
        {
            List<Usuario> usuarios = new List<Usuario>();
            try
            {

                using (OlimpycsLondonEntities entities = new OlimpycsLondonEntities())
                {
                    List<USUARIO> usuariosDB = entities.USUARIO.ToList();
                    Usuario usuario = null;
                    foreach (USUARIO usuarioDB in usuariosDB)
                    {
                        usuario = GetUsuarioDomain(usuarioDB);
                        usuarios.Add(usuario);
                    }
                }
            }
            catch (Exception ex)
            { throw ex; }
            return usuarios;

        }


        #endregion

        #region  Roles y Permisos

        public Rol GetRolByID(int rolID)
        {

            Rol rol;
            using (OlimpycsLondonEntities context = new OlimpycsLondonEntities())
            {
                try
                {
                    ROL rolEntity = context.ROL.FirstOrDefault(r => r.ID == rolID);
                    rol = GetRolDomain(rolEntity);
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }
            return rol;
        }

        private List<PERMISO> GetPermisosByRolID(int rolID)
        {
            using (OlimpycsLondonEntities context = new OlimpycsLondonEntities())
            {
                try
                {
                    var s = from p in context.PERMISO
                            join r in context.ROL_PERMISO
                            on p.ID equals r.PERMISO
                            where p.ID == rolID
                            select p;

                    return s.ToList();
                }
                catch (Exception ex)
                {
                    throw (ex);
                }
            }
        }

        public List<Rol> GetRolesByUserIDDomain(List<ROL> rolesDB)
        {
            try
            {
                Rol rol = null;
                List<Rol> roles = null;
                foreach (ROL rolDB in rolesDB)
                {
                    rol = GetRolDomain(rolDB);
                    roles.Add(rol);

                }
                return roles;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        public List<Rol> GetRolesByUserID(int userID)
        {
            using (OlimpycsLondonEntities context = new OlimpycsLondonEntities())
            {
                Rol rol = null;
                List<Rol> roles = new List<Rol>();

                try
                {
                    context.USUARIO_ROL.MergeOption = System.Data.Objects.MergeOption.NoTracking;
                    var query = from ur in context.USUARIO_ROL
                                where ur.USUARIO1.ID == userID
                                select ur.ROL1;

                    List<ROL> listROL = query.ToList();

                    foreach (ROL rolDB in listROL)
                    {
                        rol = GetRolDomain(rolDB);
                        roles.Add(rol);
                    }
                    return roles;

                }
                catch (Exception ex)
                {
                    throw (ex);
                }
            }

        }

        private List<ROL> GetRoles()
        {
            using (OlimpycsLondonEntities context = new OlimpycsLondonEntities())
            {
                try
                {
                    var s = from r in context.ROL
                            select r;

                    return s.ToList();
                }
                catch (Exception ex)
                {
                    throw (ex);
                }
            }

        }

        public List<Rol> GetAllRoles()
        {

            List<Rol> roles = new List<Rol>();

            using (OlimpycsLondonEntities entities = new OlimpycsLondonEntities())
            {
                List<ROL> rolesDB = entities.ROL.ToList();
                Rol rol = null;
                foreach (ROL rolDB in rolesDB)
                {
                    rol = GetRolDomain(rolDB);
                    roles.Add(rol);
                }
            }

            return roles;

        }

        #endregion












    }
}
